import { memo, useEffect, useRef, useState } from 'react'
import { HsAdminSpin } from '@hs-admin/base-components'
import {
  postCompanyInfoDetailQueryShareholderInformation,
  getCompanyInfoDetailEquityRelationship,
  getCompanyInfoDetailQueryBusinessInformation
} from '@/api/companyDetail/BasicInfor'
import G6 from '@antv/g6'

let graph: any

const EquityInformation = (props: any) => {
  const { companyCode, hiddenModule } = props

  const [loading, setLoading] = useState(false)

  /** 图表基础字号 */
  const fontSize = 16

  const containerData: any = useRef({
    name: '',
    hasChild: 1,
    collapsed: false,
    children: [],
    /** 有子级的加 */
    anchorPoints: [
      [1, 0.5],
      [0, 0.5]
    ]
  })

  /**
   * @description 获取文本的长度
   * @param str 文本
   * @param maxWidth 设置的最大长度
   * @returns number 最大长度
   */
  const getTextSize = (str: string, _maxWidth: number) => {
    const width = G6.Util.getTextSize(str, fontSize)[0]
    /** 若需要省略号，tooltip模式，可在此设置 */
    // return width > maxWidth ? maxWidth : width
    return width
  }

  /**
   * @description 文本超出隐藏 (字段, 最大长度, 字体大小)
   * @param str 文本
   * @param maxWidth 长度
   * @returns string 返回文本
   */
  const fittingString = (str: string, maxWidth: number) => {
    const ellipsis = '...'
    const ellipsisLength = G6.Util.getTextSize(ellipsis, fontSize)[0]
    let currentWidth = 0
    let res = str
    const pattern = new RegExp('[\u4E00-\u9FA5]+')
    str.split('').forEach((letter: any) => {
      if (currentWidth > maxWidth - ellipsisLength) return
      if (pattern.test(letter)) {
        currentWidth += fontSize
      } else {
        currentWidth += G6.Util.getLetterWidth(letter, fontSize)
      }
      if (currentWidth > maxWidth - ellipsisLength) {
        /** 若需要省略号，tooltip模式，可在此设置 */
        // res = `${str.substr(0, i)}${ellipsis}`
        res = str
      }
    })
    return res
  }

  const getData = async () => {
    // 获取当前企业名称
    getCompanyInfoDetailQueryBusinessInformation({ companyCode: companyCode || 'f70584e2d755ebcd7b58a11a281b0e70' }).then((res) => {
      containerData.current.name = res.data.companyName
    })

    const code = JSON.parse(JSON.stringify(companyCode))

    const promiseList: any[] = [0, 1].map((type) =>
      getCompanyInfoDetailEquityRelationship({
        type,
        code
      })
    )
    promiseList.unshift(
      postCompanyInfoDetailQueryShareholderInformation({
        current: 1,
        pageSize: 999,
        companyCode: code
      })
    )

    setLoading(true)
    Promise.all(promiseList).then((resList: any) => {
      const [res0, res1, res2] = resList

      // 过滤重复
      res0.data.list = res0.data.list.filter((item: any) => !res1.data.find((ele: any) => ele.name === item.sholderName))
      const leftList = [
        ...res0.data.list.map((item: any) => {
          return {
            name: item.sholderName,
            proportion: item.proportion,
            code: '',
            hasChild: 0
          }
        }),
        ...res1.data
      ]

      // 父公司放左侧
      leftList.forEach((k) => {
        /** anchorPoints用来设置折现拐点的，一定要设置！！！！！ */
        if (k.hasChild === 1) {
          /** 有子级的 */
          k.anchorPoints = [
            [1, 0.5],
            [0, 0.5]
          ]
        } else {
          /** 无子级的 */
          k.anchorPoints = [[1, 0.5]]
        }
        /** position用于判断节点怎么画 */
        k.position = 'left'

        /** category用于点击加载传递参数 */
        k.category = 0

        /** 新加载的数据初始状态都为折叠状态 */
        k.collapsed = true
      })
      // 子公司放右侧
      res2.data.forEach((k: any) => {
        if (k.hasChild === 1) {
          /** 有子级的 */
          k.anchorPoints = [
            [1, 0.5],
            [0, 0.5]
          ]
        } else {
          /** 无子级的 */
          k.anchorPoints = [[0, 0.5]]
        }
        /** category用于点击加载传递参数 */
        k.position = 'right'

        /** position用于判断节点怎么画 */
        k.category = 1

        /** 新加载的数据初始状态都为折叠状态 */
        k.collapsed = true
      })
      containerData.current.children = [...leftList, ...res2.data]

      setLoading(false)

      /** 有值画图 */
      if (containerData.current.children.length) {
        init()
        hiddenModule(true)
      } else {
        /** 无值隐藏该模块 */
        setLoading(false)
      }
    })
  }

  /** 初始化图表 */
  function init() {
    /** 自定义节点 */
    G6.registerNode('tree-node', {
      draw(cfg: any, group: any) {
        let rect: any
        /** 右侧 */
        if (cfg.position === 'left') {
          /** 左侧盒子 */
          rect = group.addShape('rect', {
            attrs: {
              x: 210 - getTextSize(cfg.name, 210), // x 轴移动距离
              y: 0, // y 轴移动距离
              width: getTextSize(cfg.name, 210) + 54, // 宽
              height: 40, // 高
              fill: '#fff',
              stroke: '#E6E6E6',
              fontSize: 16,
              fontWeight: 600,
              radius: 4,
              cursor: cfg.code ? 'pointer' : 'not-allowed'
            },
            name: 'big-rect-shape'
          })
          /** 左侧文本 */
          group.addShape('text', {
            attrs: {
              text: fittingString(cfg.name, 210),
              x: 210 - getTextSize(cfg.name, 210) + 27,
              y: 20,
              fontSize: 16,
              textAlign: 'left',
              textBaseline: 'middle',
              fill: '#333333',
              cursor: cfg.code ? 'pointer' : 'not-allowed'
            },
            name: 'text-shape'
          })
        }

        /** 右侧 */
        if (cfg.position === 'right') {
          /** 右侧盒子 */
          rect = group.addShape('rect', {
            attrs: {
              x: 0, // x 轴移动距离
              y: 0, // y 轴移动距离
              width: getTextSize(cfg.name, 210) + 54, // 宽
              height: 40, // 高
              fill: '#fff',
              stroke: '#E6E6E6',
              fontSize: 16,
              fontWeight: 600,
              radius: 4,
              cursor: 'pointer'
            },
            name: 'big-rect-shape'
          })

          /** 右侧文本 */
          group.addShape('text', {
            attrs: {
              text: fittingString(cfg.name, 210),
              x: 27,
              y: 20,
              fontSize: 16,
              textAlign: 'left',
              textBaseline: 'middle',
              fill: '#333333',
              cursor: 'pointer'
            },
            name: 'text-shape'
          })
        }

        /** 根节点 */
        if (cfg.depth === 0) {
          /** 盒子 */
          rect = group.addShape('rect', {
            attrs: {
              x: 0, // x 轴移动距离
              y: 0, // y 轴移动距离
              width: getTextSize(cfg.name, 210) + 54, // 宽
              height: 40, // 高
              fill: '#0779FF',
              stroke: '#E6E6E6', // 边框色
              fontSize: 16,
              fontWeight: 600,
              radius: 4,
              cursor: 'pointer'
            },
            name: 'big-rect-shape'
          })

          /** 文本 */
          group.addShape('text', {
            attrs: {
              text: fittingString(cfg.name, 210),
              x: 27,
              y: 20,
              fontSize: 16,
              textAlign: 'left',
              textBaseline: 'middle',
              fill: '#fff',
              cursor: 'pointer'
            },
            name: 'text-shape'
          })
        }

        /** 添加节点上方额外信息，这里是股权占比 */
        const text2 = group.addShape('text', {
          attrs: {
            text: cfg.proportion ? `${cfg.proportion}%` : '未公布',
            x: 0,
            y: 0,
            r: 0,
            textAlign: 'left',
            stroke: '#fff', // 增加白色描边解决残影问题
            lineWidth: 4, // 增加白色描边解决残影问题
            textBaseline: 'middle',
            fill: cfg.name === containerData.name ? '#fff' : '#999999', // 根节点设置底色与背景相同，隐藏
            cursor: 'pointer'
          },
          name: 'text-shape2'
        })
        const bbox2 = text2.getBBox()
        /** 左侧额外信息 */
        if (cfg.position === 'left') {
          text2.attr({
            x: 210 - getTextSize(cfg.name, 210) + 25,
            y: -bbox2.height / 2
          })
        } else {
          /** 右侧额外信息 */
          text2.attr({
            x: getTextSize(cfg.name, 210),
            y: -bbox2.height / 2,
            r: 6
          })
        }

        /** 根据是否有子节点，添加按钮 */
        /** 有子级且层级不为3的展示按钮 */
        const hasChildren = cfg.hasChild === 1 && cfg.depth !== 3
        if (hasChildren) {
          /** 左侧 */
          if (cfg.position === 'left') {
            group.addShape('marker', {
              attrs: {
                x: 210 - getTextSize(cfg.name, 210) + 15,
                y: 19,
                r: 6,
                symbol: cfg.collapsed ? G6.Marker.expand : G6.Marker.collapse,
                stroke: '#666',
                fill: '#fff',
                lineWidth: 1,
                cursor: 'pointer' // 鼠标变手
              },
              name: 'collapse-icon',
              modelId: cfg.id
            })
          } else {
            /** 右侧，同时也是根节点右侧按钮 */
            group.addShape('marker', {
              attrs: {
                x: getTextSize(cfg.name, 210) + 39,
                y: 19,
                r: 6,
                symbol: cfg.collapsed ? G6.Marker.expand : G6.Marker.collapse,
                stroke: '#666',
                fill: '#fff',
                lineWidth: 1,
                cursor: 'pointer' // 鼠标变手
              },
              name: 'collapse-icon',
              modelId: cfg.id
            })
          }
        }
        /** 根节点左侧按钮 */
        if (cfg.depth === 0) {
          group.addShape('marker', {
            attrs: {
              x: 15,
              y: 19,
              r: 6,
              symbol: cfg.collapsed ? G6.Marker.expand : G6.Marker.collapse,
              stroke: '#666',
              fill: '#fff',
              lineWidth: 1,
              cursor: 'pointer' // 鼠标变手
            },
            name: 'collapse-icon',
            modelId: cfg.id
          })
        }
        return rect
      }
    })

    /** 自定义边 */
    G6.registerEdge(
      'line-arrow',
      {
        getPath(points: any) {
          const startPoint = points[0]
          const endPoint = points[1]
          return [
            ['M', startPoint.x, startPoint.y],
            ['L', endPoint.x / 3 + (2 / 3) * startPoint.x, startPoint.y],
            ['L', endPoint.x / 3 + (2 / 3) * startPoint.x, endPoint.y],
            ['L', endPoint.x, endPoint.y]
          ]
        }
      },
      'line'
    )
    const container = document.getElementById('container') as HTMLElement

    const width = container?.scrollWidth || 500

    const height = container?.scrollHeight || 500

    graph?.destroy?.()

    graph = new G6.TreeGraph({
      container: container,
      width,
      height,
      plugins: [],
      modes: {
        default: [
          'drag-canvas',
          'zoom-canvas',
          /** 高亮节点与边 */
          'activate-relations'
        ]
      },
      defaultNode: {
        type: 'tree-node'
      },
      defaultEdge: {
        /** 自定义边 */
        type: 'line-arrow',
        style: {
          stroke: '#E6E6E6'
        }
      },
      layout: {
        type: 'mindmap',
        direction: 'H',
        getId: function getId(d: any) {
          return d.id
        },
        getHeight: () => {
          return 32
        },
        getWidth: (_d: any) => {
          return 120
        },
        getVGap: () => {
          return 20
        },
        getHGap: () => {
          return 160
        },
        /** 将节点动态分边 */
        getSide: (d: any) => {
          if (d.data.position === 'left') {
            return 'left'
          }
          return 'right'
        }
      }
    })

    /** 点击企业名称弹出又一个企业详情，无限套娃 */
    const handleCompanyNameClick = (evt: any) => {
      const model = evt.item.getModel()
      /** 根节点不弹 */
      if (model.depth === 0 || !model.code) return
      // showModal.value = true
      window.open(`/CompanyDetail?companyCode=${model.code}`, '_blank')
    }
    /** 监听文本点击 */
    graph.on('text-shape:click', (e: any) => {
      handleCompanyNameClick(e)
    })

    /** 监听按钮点击 */
    graph.on('collapse-icon:click', async (evt: any) => {
      /** 被操作的节点 item */
      const item = evt.item
      /** 被操作的节点数据 */
      const model = item?.getModel() as any

      /** 只能下钻到3级 */
      if (model.depth === 3) return

      /** 子级数据已请求完成的直接收起跟展开，并更换按钮 */
      const target = evt.target
      const id = target.get('modelId')
      const item2 = graph.findById(id)
      const nodeModel = item2.getModel() as any
      nodeModel.collapsed = !nodeModel.collapsed
      graph.layout()
      graph.setItemState(item2, 'collapse', nodeModel.collapsed)
      graph.updateItem(item2, {
        collapsed: nodeModel.collapsed
      })

      /** 有子级且子级还未获取数据的节点，调用接口获取子节点数据，然后展开该节点 */
      if (model.hasChild === 1 && !model.children?.length) {
        setLoading(true)

        const res: any = await getCompanyInfoDetailEquityRelationship({
          type: model.category,
          code: model.code
        })

        res.data.forEach((k: any) => {
          /** anchorPoints用来设置折现拐点的，一定要设置！！！！！ */
          /** 有子级的 */
          if (k.hasChild === 1) {
            k.anchorPoints = [
              [1, 0.5],
              [0, 0.5]
            ]
          } else if (model.category === 0) {
            /** 无子级的, 在左侧的 */
            k.anchorPoints = [[1, 0.5]]
          } else {
            /** 无子级的, 在右侧的 */
            k.anchorPoints = [[0, 0.5]]
          }
          /** id不能重复，拼上节点是左侧，还是右侧，用于判断连线箭头的方向 */
          let splitStr = k.code + Date.now()
          if (!k.code) {
            splitStr = Date.now()
          }
          k.id = (model.category === 0 ? 'left' : 'right') + splitStr
          /** category用于点击加载传递参数 */
          k.category = model.category

          /** position用于判断节点怎么画 */
          k.position = model.category === 0 ? 'left' : 'right'

          /** 新加载的数据初始状态都为折叠状态 */
          k.collapsed = true
        })

        /** 展开当前节点 */
        model.collapsed = false
        /** 更新子节点 */
        graph.updateChildren(res.data, model.id)

        setLoading(false)
      }

      /** 将中心动画地移动到当前操作节点，并配置动画 */
      graph.focusItem(evt.item as any, true, {
        easing: 'easeCubic',
        duration: 400
      })
    })

    /** 这里重复接入，是为了初始化数据，为了下方的条件判断 */
    graph.data(containerData.current)
    graph.render()
    graph.fitView()

    /** 该方法可以为不同边进行不同的配置 */
    graph.edge(function (e: any) {
      const id = e.id as string
      const isRight = id.indexOf('left') === -1

      /** 右侧给终止箭头 */
      if (isRight) {
        return {
          style: {
            endArrow: {
              path: 'M 0,0 L 12,6 L 12,-6 Z',
              fill: '#E6E6E6'
            }
          }
        }
      }

      /** 左侧侧给终止箭头 */
      return {
        style: {
          startArrow: {
            path: 'M 0,0 L 12,6 L 12,-6 Z',
            fill: '#E6E6E6'
          }
        }
      }
    })

    /** 控制初始展开层级 */
    G6.Util.traverseTree(containerData.current, function (item: any) {
      if (item.depth > 0) {
        /** collapsed为true时默认收起 */
        item.collapsed = true
      }
      item.id = `${item.name}${item.x}${item.y}${item.position || ''}` // id不能重复，拼上节点是左侧，还是右侧，用于判断连线箭头的方向
    })

    graph.data(containerData.current)

    graph.render()

    graph.fitCenter()

    if (typeof window !== 'undefined')
      window.onresize = () => {
        if (!graph || graph.get('destroyed')) return
        if (!container || !container.scrollWidth || !container.scrollHeight) return
        graph.changeSize(container.scrollWidth, container.scrollHeight)
      }
  }
  useEffect(() => {
    getData()
  }, [])
  return (
    <div id="股权关系图">
      {loading && <HsAdminSpin />}
      <div className="second_title">股权关系图</div>
      <div className="chart_box" style={{ height: '500px', width: '100%' }}>
        <div id="container"></div>
      </div>
    </div>
  )
}
export default memo(EquityInformation)
